package cn.lg.soar.cloud.core.config;

import cn.lg.soar.database.annotations.SoarTransactional;
import io.seata.tm.api.GlobalTransaction;
import io.seata.tm.api.GlobalTransactionContext;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * seata 事务处理
 * @author luguoxiang 469599794@qq.com
 * @Date: 2024/3/1 21:54
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@ConditionalOnClass(name = "io.seata.tm.api.GlobalTransactionContext")
@Aspect
@Component
public class SoarSeataTransactionalAspect {

    @Around("@annotation(soarTransactional)")
    public Object around(ProceedingJoinPoint point, SoarTransactional soarTransactional) throws Throwable {
        boolean isNew = false;
        GlobalTransaction transaction = GlobalTransactionContext.getCurrent();
        if (transaction == null) {
            transaction = GlobalTransactionContext.getCurrentOrCreate();
            isNew = true;
        }

        Object proceed;
        try {
            if (isNew) {
                transaction.begin();
            }
            proceed = point.proceed();
            if (isNew) {
                transaction.commit();
            }
        } catch (Throwable ex) {
            if (isNew && transaction != null) {
                // 判断是否需要回滚
                Class<? extends Throwable>[] rollbackClasses = soarTransactional.rollbackFor();
                if (rollbackClasses.length == 0 || Arrays.stream(rollbackClasses).anyMatch(e -> e.isInstance(ex))) {
                    transaction.rollback();
                }
            }
            throw ex; // 重新抛出异常
        }
        return proceed;
    }
}